package edu.umd.clip.lm.model.decoding;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;

import edu.umd.clip.lm.model.*;
import edu.umd.clip.lm.model.decoding.TrellisSlice.SliceItem;
import edu.umd.clip.lm.util.tree.BinaryTree;
/**
 * @author Denis Filimonov <den@cs.umd.edu>
 *
 */
class FuturePredictions {
	static class FuturePrediction {
		private ArrayList<SliceItem> prevLinks;
		private PredictionKey cluster;

		public FuturePrediction(PredictionKey cluster) {
			this.cluster = cluster;
			prevLinks = new ArrayList<SliceItem>(3);
		}
		
		public void addPrediction(SliceItem item) {
			if (!prevLinks.contains(item)) {
				prevLinks.add(item);
			}
		}

		public ArrayList<SliceItem> getPrevLinks() {
			return prevLinks;
		}

		public PredictionKey getCluster() {
			return cluster;
		}
	}
	
	private HashMap<PredictionKey, FuturePredictions.FuturePrediction> predictions;
	
	public static class PredictionKey {
		public final BinaryTree<HistoryTreePayload> nodes[];
		
		public PredictionKey(BinaryTree<HistoryTreePayload>[] nodes) {
			this.nodes = nodes;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + Arrays.hashCode(nodes);
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (!(obj instanceof PredictionKey))
				return false;
			PredictionKey other = (PredictionKey) obj;
			if (!Arrays.equals(nodes, other.nodes))
				return false;
			return true;
		}

	}
	
	public FuturePredictions() {
		predictions = new HashMap<PredictionKey, FuturePredictions.FuturePrediction>();
	}
	
	public void addPrediction(BinaryTree<HistoryTreePayload>[] nodes, SliceItem prevItem) {
		PredictionKey key = new PredictionKey(nodes); 
		FuturePredictions.FuturePrediction prediction = predictions.get(key);
		if (prediction == null) {
			prediction = new FuturePrediction(key);
			predictions.put(key, prediction);
		}
		prediction.addPrediction(prevItem);
	}

	public HashMap<PredictionKey, FuturePredictions.FuturePrediction> getPredictions() {
		return predictions;
	}
	
}